qblog.h(3) | libqb | qblog.h(3) |
NAME¶
qblog.h - The logging API provides four main parts (basics, filtering, threading & blackbox).
SYNOPSIS¶
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>
#include <qb/qbutil.h>
#include <qb/qbconfig.h>
Data Structures¶
struct qb_log_callsite
An instance of this structure is created in a special ELF section at every
dynamic debug callsite. union qb_log_ctl2_arg_t
Macros¶
#define LOG_TRACE (LOG_DEBUG + 1)
#define QB_LOG_MAX_LEN 512
#define QB_LOG_STRERROR_MAX_LEN 128
#define QB_LOG_INIT_DATA(name)
#define QB_LOG_TAG_LIBQB_MSG_BIT 31
#define QB_LOG_TAG_LIBQB_MSG (1U << QB_LOG_TAG_LIBQB_MSG_BIT)
#define qb_logt(priority, tags, fmt, args...)
This is the function to generate a log message if you want to manually add
tags. #define qb_log(priority, fmt, args...)
qb_logt(priority, 0, fmt, ##args)
This is the main function to generate a log message. #define QB_XC ''
#define QB_XS ''
#define qb_perror(priority, fmt, args...)
This is similar to perror except it goes into the logging system. #define
qb_enter() qb_log(LOG_TRACE, 'ENTERING %s()', __func__)
#define qb_leave() qb_log(LOG_TRACE, 'LEAVING %s()',
__func__)
#define QB_LOG_CTL2_I32(a) ((qb_log_ctl2_arg_t) { .i32 = (a) })
#define QB_LOG_CTL2_S(a) ((qb_log_ctl2_arg_t) { .s = (a) })
Typedefs¶
typedef const char *(* qb_log_tags_stringify_fn) (uint32_t
tags)
typedef void(* qb_log_filter_fn) (struct qb_log_callsite *cs)
typedef void(* qb_log_logger_fn) (int32_t t, struct
qb_log_callsite *cs, time_t timestamp, const char *msg)
typedef void(* qb_log_vlogger_fn) (int32_t t, struct
qb_log_callsite *cs, time_t timestamp, va_list ap)
typedef void(* qb_log_close_fn) (int32_t t)
typedef void(* qb_log_reload_fn) (int32_t t)
Enumerations¶
enum qb_log_target_slot { QB_LOG_TARGET_START,
QB_LOG_TARGET_STATIC_START = QB_LOG_TARGET_START,
QB_LOG_SYSLOG = QB_LOG_TARGET_STATIC_START, QB_LOG_STDERR,
QB_LOG_BLACKBOX, QB_LOG_STDOUT,
QB_LOG_TARGET_STATIC_MAX, QB_LOG_TARGET_STATIC_END =
QB_LOG_TARGET_STATIC_MAX - 1, QB_LOG_TARGET_DYNAMIC_START =
QB_LOG_TARGET_STATIC_MAX, QB_LOG_TARGET_MAX = 32,
QB_LOG_TARGET_DYNAMIC_END = QB_LOG_TARGET_MAX - 1,
QB_LOG_TARGET_END = QB_LOG_TARGET_DYNAMIC_END }
enum qb_log_target_state { QB_LOG_STATE_UNUSED = 1,
QB_LOG_STATE_DISABLED = 2, QB_LOG_STATE_ENABLED = 3 }
enum qb_log_conf { QB_LOG_CONF_ENABLED,
QB_LOG_CONF_FACILITY, QB_LOG_CONF_DEBUG,
QB_LOG_CONF_SIZE, QB_LOG_CONF_THREADED,
QB_LOG_CONF_PRIORITY_BUMP, QB_LOG_CONF_STATE_GET,
QB_LOG_CONF_FILE_SYNC, QB_LOG_CONF_EXTENDED,
QB_LOG_CONF_IDENT }
enum qb_log_filter_type { QB_LOG_FILTER_FILE,
QB_LOG_FILTER_FUNCTION, QB_LOG_FILTER_FORMAT,
QB_LOG_FILTER_FILE_REGEX, QB_LOG_FILTER_FUNCTION_REGEX,
QB_LOG_FILTER_FORMAT_REGEX }
enum qb_log_filter_conf { QB_LOG_FILTER_ADD,
QB_LOG_FILTER_REMOVE, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_TAG_SET, QB_LOG_TAG_CLEAR, QB_LOG_TAG_CLEAR_ALL
}
Functions¶
struct qb_log_callsite __attribute__ ((aligned(8)))
void qb_log_real_ (struct qb_log_callsite *cs,...)
Internal function: use qb_log() or qb_logt() void
qb_log_real_va_ (struct qb_log_callsite *cs, va_list ap)
void qb_log_from_external_source (const char *function, const
char *filename, const char *format, uint8_t priority,
uint32_t lineno, uint32_t tags,...)
__attribute__((format(printf
This function is to import logs from other code (like libraries) that provide
a callback with their logs. void struct qb_log_callsite *
qb_log_callsite_get (const char *function, const char
*filename, const char *format, uint8_t priority,
uint32_t lineno, uint32_t tags)
Get or create a callsite at the given position. void
qb_log_from_external_source_va (const char *function, const
char *filename, const char *format, uint8_t priority,
uint32_t lineno, uint32_t tags, va_list ap)
__attribute__((format(printf
void qb_log_init (const char *name, int32_t facility, uint8_t
priority)
Init the logging system. void qb_log_fini (void)
Logging system finalization function. int32_t qb_log_callsites_register
(struct qb_log_callsite *_start, struct qb_log_callsite
*_stop)
If you are using dynamically loadable modules via dlopen() and you load them
after qb_log_init() then after you load the module you will need to
do the following to get the filters to work in that module: void
qb_log_callsites_dump (void)
Dump the callsite info to stdout. int32_t qb_log_ctl (int32_t target,
enum qb_log_conf conf_type, int32_t arg)
Main logging control function. int32_t qb_log_ctl2 (int32_t target,
enum qb_log_conf conf_type, qb_log_ctl2_arg_t arg)
Extension of main logging control function accepting also strings. int32_t
qb_log_filter_ctl (int32_t value, enum qb_log_filter_conf c,
enum qb_log_filter_type type, const char *text, uint8_t low_priority)
This allows you modify the 'tags' and 'targets' callsite fields at runtime.
int32_t qb_log_filter_ctl2 (int32_t value, enum
qb_log_filter_conf c, enum qb_log_filter_type type, const char
*text, uint8_t high_priority, uint8_t low_priority)
This extends qb_log_filter_ctl() by been able to provide a
high_priority. int32_t qb_log_filter_fn_set (qb_log_filter_fn
fn)
Instead of using the qb_log_filter_ctl() functions you can apply the
filters manually by defining a callback and setting the targets field using
qb_bit_set() and qb_bit_clear() like the following below: void
qb_log_tags_stringify_fn_set (qb_log_tags_stringify_fn fn)
Set the callback to map the 'tags' bit map to a string. void
qb_log_format_set (int32_t t, const char *format)
Set the format specifiers. int32_t qb_log_file_open (const char
*filename)
Open a log file. void qb_log_file_close (int32_t t)
Close a log file and release is resources. int32_t
qb_log_thread_priority_set (int32_t policy, int32_t priority)
When using threaded logging set the pthread policy and priority. int32_t
qb_log_thread_start (void)
Start the logging pthread. ssize_t qb_log_blackbox_write_to_file (const
char *filename)
Write the blackbox to file. void qb_log_blackbox_print_from_file (const
char *filename)
Read the blackbox for file and print it out. int32_t qb_log_custom_open
(qb_log_logger_fn log_fn, qb_log_close_fn close_fn,
qb_log_reload_fn reload_fn, void *user_data)
Open a custom log target. void qb_log_custom_close (int32_t t)
Close a custom log target and release is resources. void *
qb_log_target_user_data_get (int32_t t)
Retrieve the user data set by either qb_log_custom_open or
qb_log_target_user_data_set. int32_t qb_log_target_user_data_set
(int32_t t, void *user_data)
Associate user data with this log target. void qb_log_target_format
(int32_t target, struct qb_log_callsite *cs, time_t timestamp, const
char *formatted_message, char *output_buffer)
Format the callsite and timestamp info according to the format. int32_t
qb_log_facility2int (const char *fname)
Convert string 'auth' to equivalent number 'LOG_AUTH' etc. const char *
qb_log_facility2str (int32_t fnum)
Convert number 'LOG_AUTH' to equivalent string 'auth' etc.
Variables¶
const char * function
const char * filename
const char * format
uint8_t priority
uint32_t lineno
uint32_t targets
uint32_t tags
enum qb_log_target_slot __attribute__
Detailed Description¶
The logging API provides four main parts (basics, filtering, threading & blackbox).
The idea behind this logging system is not to be prescriptive but to provide a set of tools to help the developer achieve what they want quickly and easily.
Basic logging API.
Simplest possible use:
main() {
qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
// ...
qb_log(LOG_WARNING, "watch out");
// ...
qb_log_fini(); }
Note:
Configuring log targets.
qb_log_ctl(B_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
To enable a target do the following:
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
syslog, stderr, the blackbox, and stdout are static (they don't need to be created, just enabled or disabled). However, you can open multiple logfiles (falling within inclusive range QB_LOG_TARGET_DYNAMIC_START up to QB_LOG_TARGET_DYNAMIC_END). To do this, use the following code:
mytarget = qb_log_file_open("/var/log/mylogfile"); qb_log_ctl(mytarget, QB_LOG_CONF_ENABLED, QB_TRUE);
Once your targets are enabled/opened, you can configure them as follows: Configure the size of blackbox:
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024*10);
Make logging to file threaded:
qb_log_ctl(mytarget, QB_LOG_CONF_THREADED, QB_TRUE);
Sometimes, syslog daemons are (pre)configured to filter messages not exceeding a particular priority. When this happens to be the logging target, the designated priority of the message is passed along unchanged, possibly resulting in message loss. For messages up to LOG_DEBUG importance, this can be worked around by proportionally bumping the priorities to be passed to syslog (here, the step is such that LOG_DEBUG gets promoted to LOG_INFO):
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP,
LOG_INFO - LOG_DEBUG);
To ensure all logs to file targets are fsync'ed (new messages expressly transferred to the storage device as they keep coming, otherwise defaults to QB_FALSE):
qb_log_ctl(mytarget, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
Filtering messages.
- 1.
- filename + priority
- 2.
- function name + priority
- 3.
- format string + priority
So to make all logs from evil_function() go to stderr, do the following:
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FUNCTION, "evil_function", LOG_TRACE);
So to make all logs from totem* (with a priority <= LOG_INFO) go to stderr, do the following:
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "totem", LOG_INFO);
So to make all logs with the substring 'ringbuffer' go to stderr, do the following:
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FORMAT, "ringbuffer", LOG_TRACE);
Thread safe non-blocking logging.
To achieve non-blocking logging, so that any calls to write() or syslog() will not hold up your program, you can use threaded logging as well.
Threaded logging use:
main() {
qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
// ...
daemonize();
// call this after you fork()
qb_log_thread_start();
// ...
qb_log(LOG_WARNING, "watch out");
// ...
qb_log_fini(); }
A blackbox for in-field diagnosis.
Note:
Blackbox usage:
static void sigsegv_handler(int sig) {
(void)signal (SIGSEGV, SIG_DFL);
qb_log_blackbox_write_to_file("simple-log.fdata");
qb_log_fini();
raise(SIGSEGV); } main() {
signal(SIGSEGV, sigsegv_handler);
qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024*10);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
// ...
qb_log(LOG_WARNING, "watch out");
// ...
qb_log_fini(); }
Tagging messages.
const char* my_tags_stringify(uint32_t tags) {
if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT) {
return "libqb";
} else if (tags == 3) {
return "three";
} else {
return "MAIN";
} } main() {
// ...
qb_log_tags_stringify_fn_set(my_tags_stringify);
qb_log_format_set(QB_LOG_STDERR, "[%5g] %p %b");
// ...
qb_logt(LOG_INFO, 3, "hello");
qb_logt(LOG_INFO, 0, "hello"); }
The code above will produce:
[libqb] some message [three] info hello [MAIN ] info hello
Macro Definition Documentation¶
#define LOG_TRACE (LOG_DEBUG + 1)¶
#define qb_enter() qb_log(LOG_TRACE, 'ENTERING %s()', __func__)¶
#define qb_leave() qb_log(LOG_TRACE, 'LEAVING %s()', __func__)¶
#define qb_log(priority, fmt, args...) qb_logt(priority, 0, fmt, ##args)¶
This is the main function to generate a log message.
Parameters:
fmt usual printf style format specifiers
args usual printf style args
#define QB_LOG_CTL2_I32(a) ((qb_log_ctl2_arg_t) { .i32 = (a) })¶
#define QB_LOG_CTL2_S(a) ((qb_log_ctl2_arg_t) { .s = (a) })¶
#define QB_LOG_INIT_DATA(name)¶
#define QB_LOG_MAX_LEN 512¶
#define QB_LOG_STRERROR_MAX_LEN 128¶
#define QB_LOG_TAG_LIBQB_MSG (1U << QB_LOG_TAG_LIBQB_MSG_BIT)¶
#define QB_LOG_TAG_LIBQB_MSG_BIT 31¶
#define qb_logt(priority, tags, fmt, args...)¶
Value:
do { struct qb_log_callsite* descriptor_pt = qb_log_callsite_get(__func__, __FILE__, fmt, priority, __LINE__, tags); qb_log_real_(descriptor_pt, ##args); } while(0)
This is the function to generate a log message if you want to manually add tags.
Parameters:
tags this is a uint32_t that you can use with qb_log_tags_stringify_fn_set() to 'tag' a log message with a feature or sub-system then you can use '%g' in the format specifer to print it out.
fmt usual printf style format specifiers
args usual printf style args
#define qb_perror(priority, fmt, args...)¶
Value:
do { char _perr_buf_[QB_LOG_STRERROR_MAX_LEN]; const char *_perr_str_ = qb_strerror_r(errno, _perr_buf_, sizeof(_perr_buf_)); qb_logt(priority, 0, fmt ": %s (%d)", ##args, _perr_str_, errno); } while(0)
This is similar to perror except it goes into the logging system.
Parameters:
fmt usual printf style format specifiers
args usual printf style args
Note:
#define QB_XC ''¶
#define QB_XS ''¶
Typedef Documentation¶
typedef void(* qb_log_close_fn) (int32_t t)¶
typedef void(* qb_log_filter_fn) (struct qb_log_callsite *cs)¶
typedef void(* qb_log_logger_fn) (int32_t t, struct qb_log_callsite *cs, time_t timestamp, const char *msg)¶
typedef void(* qb_log_reload_fn) (int32_t t)¶
typedef const char*(* qb_log_tags_stringify_fn) (uint32_t tags)¶
typedef void(* qb_log_vlogger_fn) (int32_t t, struct qb_log_callsite *cs, time_t timestamp, va_list ap)¶
Enumeration Type Documentation¶
enum qb_log_conf¶
Enumerator
enum qb_log_filter_conf¶
Enumerator
enum qb_log_filter_type¶
Enumerator
enum qb_log_target_slot¶
Enumerator
enum qb_log_target_state¶
Enumerator
Function Documentation¶
struct qb_log_callsite __attribute__ ((aligned(8)))¶
void qb_log_blackbox_print_from_file (const char * filename)¶
Read the blackbox for file and print it out.
ssize_t qb_log_blackbox_write_to_file (const char * filename)¶
Write the blackbox to file.
void struct qb_log_callsite* qb_log_callsite_get (const char * function, const char * filename, const char * format, uint8_t priority, uint32_t lineno, uint32_t tags)¶
Get or create a callsite at the given position. The result can then be passed into qb_log_real_()
Parameters:
filename originating filename
format format string
priority this takes syslog priorities.
lineno file line number
tags the tag
void qb_log_callsites_dump (void)¶
Dump the callsite info to stdout.
int32_t qb_log_callsites_register (struct qb_log_callsite * _start, struct qb_log_callsite * _stop)¶
If you are using dynamically loadable modules via dlopen() and you load them after qb_log_init() then after you load the module you will need to do the following to get the filters to work in that module:
_start = dlsym (dl_handle, QB_ATTR_SECTION_START_STR); _stop = dlsym (dl_handle, QB_ATTR_SECTION_STOP_STR); qb_log_callsites_register(_start, _stop);
int32_t qb_log_ctl (int32_t target, enum qb_log_conf conf_type, int32_t arg)¶
Main logging control function.
Parameters:
conf_type configuration directive ('what to configure') that accepts int32_t argument determining the new value unless ignored for particular directive altogether (incompatible directives: QB_LOG_CONF_IDENT)
arg the new value for a state-changing configuration directive, ignored otherwise
See also:
Return values:
0 on success
qb_log_target_state for QB_LOG_CONF_STATE_GET
int32_t qb_log_ctl2 (int32_t target, enum qb_log_conf conf_type, qb_log_ctl2_arg_t arg)¶
Extension of main logging control function accepting also strings.
Parameters:
conf_type configuration directive ('what to configure') that accepts either int32_t or a null-terminated string argument determining the new value unless ignored for particular directive (compatible directives: those valid for qb_log_ctl
- •
- QB_LOG_CONF_IDENT)
arg the new value for a state-changing configuration directive, ignored otherwise; for QB_LOG_CONF_IDENT, 's' member as new identifier to openlog(), for all qb_log_ctl-compatible ones, 'i32' member is assumed (although a preferred way is to use that original function directly as it allows for more type safety)
See also:
Note:
void qb_log_custom_close (int32_t t)¶
Close a custom log target and release is resources.
int32_t qb_log_custom_open (qb_log_logger_fn log_fn, qb_log_close_fn close_fn, qb_log_reload_fn reload_fn, void * user_data)¶
Open a custom log target.
Return values:
value in inclusive range QB_LOG_TARGET_DYNAMIC_START to QB_LOG_TARGET_DYNAMIC_END (to be passed into other qb_log_* functions)
int32_t qb_log_facility2int (const char * fname)¶
Convert string 'auth' to equivalent number 'LOG_AUTH' etc.
const char* qb_log_facility2str (int32_t fnum)¶
Convert number 'LOG_AUTH' to equivalent string 'auth' etc.
void qb_log_file_close (int32_t t)¶
Close a log file and release is resources.
int32_t qb_log_file_open (const char * filename)¶
Open a log file.
Return values:
value in inclusive range QB_LOG_TARGET_DYNAMIC_START to QB_LOG_TARGET_DYNAMIC_END (to be passed into other qb_log_* functions)
int32_t qb_log_filter_ctl (int32_t value, enum qb_log_filter_conf c, enum qb_log_filter_type type, const char * text, uint8_t low_priority)¶
This allows you modify the 'tags' and 'targets' callsite fields at runtime.
int32_t qb_log_filter_ctl2 (int32_t value, enum qb_log_filter_conf c, enum qb_log_filter_type type, const char * text, uint8_t high_priority, uint8_t low_priority)¶
This extends qb_log_filter_ctl() by been able to provide a high_priority.
int32_t qb_log_filter_fn_set (qb_log_filter_fn fn)¶
Instead of using the qb_log_filter_ctl() functions you can apply the filters manually by defining a callback and setting the targets field using qb_bit_set() and qb_bit_clear() like the following below:
static void m_filter(struct qb_log_callsite *cs) {
if ((cs->priority >= LOG_ALERT &&
cs->priority <= LOG_DEBUG) &&
strcmp(cs->filename, "my_c_file.c") == 0) {
qb_bit_set(cs->targets, QB_LOG_SYSLOG);
} else {
qb_bit_clear(cs->targets, QB_LOG_SYSLOG);
} }
void qb_log_fini (void)¶
Logging system finalization function. It releases any shared memory. Stops the logging thread if running. Flushes the last messages to their destinations.
void qb_log_format_set (int32_t t, const char * format)¶
Set the format specifiers. n FUNCTION NAME f FILENAME l FILELINE p PRIORITY t TIMESTAMP b BUFFER g TAGS N name (passed into qb_log_init) P PID H hostname
Any number between % and character specify field length to pad or chop.
Note:
void qb_log_from_external_source (const char * function, const char * filename, const char * format, uint8_t priority, uint32_t lineno, uint32_t tags, ...)¶
This function is to import logs from other code (like libraries) that provide a callback with their logs.
Note:
Parameters:
filename originating filename
format format string
priority this takes syslog priorities.
lineno file line number
tags this is a uint32_t that you can use with qb_log_tags_stringify_fn_set() to 'tag' a log message with a feature or sub-system then you can use '%g' in the format specifer to print it out.
void qb_log_from_external_source_va (const char * function, const char * filename, const char * format, uint8_t priority, uint32_t lineno, uint32_t tags, va_list ap)¶
void qb_log_init (const char * name, int32_t facility, uint8_t priority)¶
Init the logging system.
Parameters:
facility default for all new targets.
priority a basic filter with this priority will be added.
void qb_log_real_ (struct qb_log_callsite * cs, ...)¶
Internal function: use qb_log() or qb_logt()
void qb_log_real_va_ (struct qb_log_callsite * cs, va_list ap)¶
void qb_log_tags_stringify_fn_set (qb_log_tags_stringify_fn fn)¶
Set the callback to map the 'tags' bit map to a string.
void qb_log_target_format (int32_t target, struct qb_log_callsite * cs, time_t timestamp, const char * formatted_message, char * output_buffer)¶
Format the callsite and timestamp info according to the format. set using qb_log_format_set() It is intended to be used from your custom logger function.
void* qb_log_target_user_data_get (int32_t t)¶
Retrieve the user data set by either qb_log_custom_open or qb_log_target_user_data_set.
int32_t qb_log_target_user_data_set (int32_t t, void * user_data)¶
Associate user data with this log target.
Note:
int32_t qb_log_thread_priority_set (int32_t policy, int32_t priority)¶
When using threaded logging set the pthread policy and priority.
Return values:
0 success
int32_t qb_log_thread_start (void)¶
Start the logging pthread.
Variable Documentation¶
enum qb_log_target_slot __attribute__¶
const char* filename¶
const char* format¶
const char* function¶
uint32_t lineno¶
uint8_t priority¶
uint32_t tags¶
uint32_t targets¶
Author¶
Generated automatically by Doxygen for libqb from the source code.
Fri Jan 13 2023 | Version 1.0.3 |